/**
 * 原型链继承
 * @summary 缺点：
 * 1、new SuperType时无法传入参数
 * 2、当原型属性是引用类型时，如下ars是一个数组，instance1和instance2共享ars，instance1.ars.push(12)后，instance2.ars的值也会变
 * 3、如果SuperType有入参，这种继承方式新建SubType时无法传入参数
 */
function protoLinkExt() {
	function SuperType() {
		this.property = true;
		this.ars = [1,2,3];
	}
	SuperType.prototype.superSay = function() {
		console.log("this is SuperType");
	}
	
	function SubType() {
		this.name = "SubType";	
	}
	SubType.prototype = new SuperType();
	SubType.prototype.subSay = function() {
		console.log("this is subType");
	}
	
	let instance1 = new SubType();
	let instance2 = new SubType();
	debugger
}

/**
 * 盗用构造函数，其实并没有实现继承
 */
function stealConstructor() {
	function SuperType(tag, age) {
		this.tag = tag;
		this.age = age;
		this.ars = [1, 2, 3];
	}
	SuperType.prototype.getAge = function() {
		console.log("super method:", this.age);
	}
	
	
	
	function SubType(tag, age) {
		SuperType.call(this, tag, age);
		this.subTag = "subType";
	}
	SubType.prototype.getSubTag = function() {
		console.log("sub method:", this.subTag);
	}
	
	let ins1 = new SubType("ins1", 12);
	let ins2 = new SubType("ins2", 14);
	
	ins1.ars.push(111);
	
	console.log(ins1, ins2, ins1.getAge === ins2.getAge, ins1.getAge(), ins2.getAge());
}

/**
 * 组合继承，结合原型链继承和盗用构造函数
 */
function mixExt() {
	function SuperType(tag, age) {
		this.tag = tag;
		this.age = age;
		this.ars = [1, 2, 3];
	}
	SuperType.prototype.getAge = function() {
		console.log("super method:", this.age);
	}
	
	
	
	function SubType(tag, age) {
		SuperType.call(this, tag, age);
		this.subTag = "subType";
	}
	SubType.prototype = new SuperType();
	
	
	SubType.prototype.getSubTag = function() {
		console.log("sub method:", this.subTag);
	}
	
	let ins1 = new SubType("ins1", 12);
	let ins2 = new SubType("ins2", 14);
	
	ins1.ars.push(111);
	
	console.log(ins1, ins2, ins1.getAge === ins2.getAge, ins1.getAge(), ins2.getAge());
}

/**
 * 原型式继承
 */
function protoExt() {
	function object(o) {
		function F() {}
		F.prototype = o;
		return new F();
	}
	let o1 = {
		n:1,
		t:2
	}
	let o2 = object(o1);
	console.log(o1, o2, o2.prototype === o1);
}

/**
 * 寄生式继承
 */
function parasiticInheritance() {
	function object(o) {
		function F() {}
		F.prototype = o;
		return new F();
	}
	
	function createAnother(original) {
		let clone = object(original);
		clone.sayHi = function() {
			console.log("ttf");
		}
		return clone;
	}
	
	let p = {
		n: 1
	}
	let ap = createAnother(p);
	ap.sayHi()
}

/**
 * 寄生式组合继承
 */
function parasiticMixExt() {
	/**
	 * 克隆对象
	 * @param o
	 * @return {F}
	 */
	function object(o) {
		function F() {}
		F.prototype = o;
		return new F();
	}
	
	/**
	 * 实现继承
	 * @param superType
	 * @param subType
	 */
	function inheritPrototype(superType, subType) {
		const prototype =  object(superType.prototype);
		prototype.constructor = subType;
		subType.prototype = prototype;
	}
	
	function SuperType(type) {this.type = type}
	SuperType.prototype.logType = function() {
		console.log(this.type);
	}
	
	function SubType(name) {
		SuperType.call(this, "subtype");
		this.name = name;
	}
	inheritPrototype(SuperType, SubType);
	SubType.prototype.sayName = function() {
		console.log(this.name);
	}
	
	let sub = new SubType("哈哈哈");
	debugger
}
parasiticMixExt();
